package model.auxillary;

import java.util.ArrayList;
import java.util.Collection;

import model.IObservable;
import view.IObserver;

/**
 * The {@code Parameter} class defines a parameter which allows to compute the
 * minimum energy consumption of a manufacturing process. Parameters store a
 * value that are used to compute other parameters.
 * @author Oliver Eckstein
 *
 */
public class Parameter implements IObservable, Comparable<Parameter> {
    
	/**
     * The parameter's name.
     */
	private final String NAME;
	
	/**
	 * The parameter's abbreviation that is used to identify a parameter inside
	 * the calculation model. 
	 */
    private final String ABBREVIATION;
    
    /**
     * The parameter's abbreviation that is shown on the view.
     */
    private final String GUI_ABBREVIATION;
    
    /**
     * The parameter's unit that is shown on the view.
     */
    private final String UNIT;
    
    /**
     * The parameter's order number. This order number is used on the view.
     */
    private int order;
    
    /**
     * An identifying ID for this parameter.
     */
    private String id;
    
    /**
     * A flag that is {@code true} when a parameter must be set by a user and
     * {@code false} when the parameter depends on calculations.
     */
    private boolean setByUser;
    
    /**
     * The parameter's value.
     */
    private Double value;
    
    /**
     * The parameter's observers.
     */
    private Collection<IObserver> observers =
            new ArrayList<IObserver>();
    
    /**
     * To create a new instance of a {@code Parameter}. It's value is set to
     * {@code Double.NaN}.
     * @param name name of the parameter.
     * @param abbreviation abbreviation of the parameter.
     * @param guiAbbreviation the abbreviation for GUI purposes.
     * @param unit the unit of the parameter.
     * @param setByUser {@code true} when parameter is set by user,
     * {@code false} otherwise.
     * @param observer the parameter's observer. 
     */
    public Parameter(
           String name,
           String abbreviation,
           String guiAbbreviation,
           String unit,
           boolean setByUser,
           IObserver observer
           )
    {
        NAME = name;        
        ABBREVIATION = abbreviation;
        GUI_ABBREVIATION = guiAbbreviation;
        UNIT = unit;
        this.setByUser = setByUser;
        value = Double.NaN;
        if(observers != null) {
        	registerObserver(observer);	
        }        
    }
    
    /**
     * To get the parameter's name.
     * @return the parameter's name.
     */
    public String getName() {
        return NAME;
    }
    
    /**
     * To get the parameter's abbreviation.
     * @return the parameter's abbreviation.
     */
    public String getAbbreviation() {
        return ABBREVIATION;
    }
    
    /**
     * To get the parameter's GUI abbreviation.
     * @return the parameter's GUI abbreviation.
     */
    public String getGuiAbbreviation()
    {
        return GUI_ABBREVIATION;
    }
    
    /**
     * To get the parameter's unit.
     * @return the parameter's unit.
     */
    public String getUnit() {
        return UNIT;
    }
    
    /**
     * To find out if parameter must be set by user or not. 
     * @return the parameter's dependence.
     */
    public boolean isSetByUser()
    {
        return setByUser;
    }
    
    /**
     * To get the parameter's order number.
     * @return the parameter's order number.
     */
    public int getOrder()
    {
        return order;
    }
    
    /**
     * To get the parameter's value.
     * @return the parameter's value.
     */
    public Double getValue() {
        return value;
    }
    
    public String getKey()	 {
    	return id;
    }
    
    /**
     * To set the parameter's value.
     * @param value value to be set.
     * @throws IllegalArgumentException
     */
    public void setValue(Double value) throws IllegalArgumentException {
        if (value == null)
            throw new IllegalArgumentException(
                    "Value of parameter must be set!");
        this.value = value;
        notifyObservers();
    }
    
    /**
     * To set the parameter's dependence.
     * @param setByUser <b>true</b> when {@code Parameter} gets set by user.
     */
    public void setDependence(boolean setByUser)
    {
        this.setByUser = setByUser;
    }
    
    /**
     * To set the parameter's order number.
     * @param order the order number.
     */
    public void setOrder(int order) {
    	this.order = order;
    }
    
    /**
     * To set the parameter's identifying key.
     * @param key the key.
     */
    public void setKey(String key) {
    	this.id = key;
    }
    
    @Override
    public void registerObserver(IObserver observer)
    {
        observers.add(observer);
    }
    
    @Override
    public void removeObserver(IObserver observer)
    {
        if(observers.contains(observer))
        {
            observers.remove(observer);            
        }        
    }
        
    @Override
    public void notifyObservers()
    {        
        for(IObserver observer : observers)
        {
            observer.update();            
        }        
    }

    @Override
    public int compareTo(Parameter that) {
        return Integer.compare(this.order, that.order);
    }
    
    @Override
    public String toString() {
        return ("Parameter_" + id + "_" + ABBREVIATION);
    }
    
    /**
     * To indicate whether this parameter was set by a user or not.
     * @return true when parameter was set by a user.
     */
    public boolean isSet() {
        return (Double.isNaN(value) ? false : true);    	
    }
}
